import { initBuffers } from "./init-buffers.js";
import { drawScene } from "./draw-scene.js";
// 从这里开始
let cubeRotation = 0.0; // 定义立体旋转变量
let deltaTime = 0;
// 当视频可以复制到纹理中时将被设置为 true
let copyVideo = false;
main()
function main() {
    const canvas = document.querySelector("#glcanvas");
    // 初始化 WebGL 上下文
    const gl = canvas.getContext("webgl");

    // 确认 WebGL 支持性
    if (!gl) {
        alert("无法初始化 WebGL，你的浏览器、操作系统或硬件等可能不支持 WebGL。");
        return;
    }

    // 使用完全不透明的黑色清除所有图像
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    // 用上面指定的颜色清除缓冲区
    gl.clear(gl.COLOR_BUFFER_BIT);


    //     // Vertex shader program
    // // 颜色
    //     const vsSource = `
    //     attribute vec4 aVertexPosition;
    //     attribute vec4 aVertexColor;

    //     uniform mat4 uModelViewMatrix;
    //     uniform mat4 uProjectionMatrix;

    //     varying lowp vec4 vColor;

    //     void main() {
    //       gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
    //   vColor = aVertexColor;
    //     }
    //   `;
    // 纹理
    const vsSource = `
    attribute vec4 aVertexPosition;
    // 模拟现实灯光
    attribute vec3 aVertexNormal;
    attribute vec2 aTextureCoord;

    // 模拟现实灯光
    uniform mat4 uNormalMatrix;
    uniform mat4 uModelViewMatrix;
    uniform mat4 uProjectionMatrix;

    varying highp vec2 vTextureCoord;
    // 模拟现实灯光
    varying highp vec3 vLighting;

    void main() {
      gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
      vTextureCoord = aTextureCoord;

       // Apply lighting effect  应用灯光影响
      highp vec3 ambientLight = vec3(0.3, 0.3, 0.3);
      highp vec3 directionalLightColor = vec3(1, 1, 1);
      highp vec3 directionalVector = normalize(vec3(0.85, 0.8, 0.75));

      highp vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0);

      highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0);
      vLighting = ambientLight + (directionalLightColor * directional);
    }
  `;
    // 颜色
    //     const fsSource = `
    //     varying lowp vec4 vColor;
    //     void main() {
    //       gl_FragColor = vColor;
    //     }
    //   `;

    // 纹理
    const fsSource = `
    varying highp vec2 vTextureCoord;
    // 模拟现实灯光
    varying highp vec3 vLighting;

    uniform sampler2D uSampler;

    void main(void) {
    // 模拟
    highp vec4 texelColor = texture2D(uSampler, vTextureCoord);
    //   gl_FragColor = texture2D(uSampler, vTextureCoord);
    gl_FragColor = vec4(texelColor.rgb * vLighting, texelColor.a);
    }
  `;


    const shaderProgram = initShaderProgram(gl, vsSource, fsSource);

    const programInfo = {
        program: shaderProgram,
        attribLocations: {
            vertexPosition: gl.getAttribLocation(shaderProgram, "aVertexPosition"),
            // vertexColor: gl.getAttribLocation(shaderProgram, "aVertexColor"),
            // 灯光
            vertexNormal: gl.getAttribLocation(shaderProgram, 'aVertexNormal'),
            // 纹理
            textureCoord: gl.getAttribLocation(shaderProgram, "aTextureCoord"),
        },
        uniformLocations: {
            projectionMatrix: gl.getUniformLocation(shaderProgram, "uProjectionMatrix"),
            modelViewMatrix: gl.getUniformLocation(shaderProgram, "uModelViewMatrix"),
            // 灯光
            normalMatrix: gl.getUniformLocation(shaderProgram, 'uNormalMatrix'),
            // 纹理
            uSampler: gl.getUniformLocation(shaderProgram, "uSampler"),
        },
    };

    // Here's where we call the routine that builds all the
    // objects we'll be drawing.
    const buffers = initBuffers(gl);

    // Load texture  使用纹理
    // const texture = loadTexture(gl, "cubetexture.png");
    // 图片变更为视频
    const texture = initTexture(gl);
    const video = setupVideo("test2.mp4");

    // Flip image pixels into the bottom-to-top order that WebGL expects.
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);


    // Draw the scene
    // drawScene(gl, programInfo, buffers);

    // 创建一个新变量来跟踪上次动画播放的时间
    var then = 0;

    // Draw the scene repeatedly 添加squareRotation随时间更改值
    function render(now) {
        now *= 0.001; // convert to seconds
        deltaTime = now - then;
        then = now;

        // 如果有视频
        if (copyVideo) {
            updateTexture(gl, texture, video);
        }

        drawScene(gl, programInfo, buffers, texture, cubeRotation);   // 绘制图形

        // 使用自上次我们更新值以来所经过的时间squareRotation来确定旋转正方形的距离 2D
        // squareRotation += deltaTime;
        // 3D
        cubeRotation += deltaTime;
        requestAnimationFrame(render);
    }
    requestAnimationFrame(render);
}




//
//  初始化着色器程序，让 WebGL 知道如何绘制我们的数据
function initShaderProgram(gl, vsSource, fsSource) {
    const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
    const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

    // 创建着色器程序

    const shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

    // 如果创建失败，alert
    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert(
            "Unable to initialize the shader program: " +
            gl.getProgramInfoLog(shaderProgram),
        );
        return null;
    }

    return shaderProgram;
}

//
// 创建指定类型的着色器，上传 source 源码并编译
//
function loadShader(gl, type, source) {
    const shader = gl.createShader(type);

    // Send the source to the shader object

    gl.shaderSource(shader, source);

    // Compile the shader program

    gl.compileShader(shader);

    // See if it compiled successfully

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert(
            "An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader),
        );
        gl.deleteShader(shader);
        return null;
    }

    return shader;
}

// //
// //
// // Initialize a texture and load an image.
// // When the image finished loading copy it into the texture.
// // 调用 WebGL 的 createTexture() 函数来创建一个 WebGL 纹理对象 texture。
// // 接下来使用 texImage2D() 以上传一个蓝色的像素点。这样我们就可以在图片下载完成之前使用这个蓝色的纹理了。
// function loadTexture(gl, url) {
//     const texture = gl.createTexture();
//     gl.bindTexture(gl.TEXTURE_2D, texture);

//     // Because images have to be downloaded over the internet
//     // they might take a moment until they are ready.
//     // Until then put a single pixel in the texture so we can
//     // use it immediately. When the image has finished downloading
//     // we'll update the texture with the contents of the image.
//     const level = 0;
//     const internalFormat = gl.RGBA;
//     const width = 1;
//     const height = 1;
//     const border = 0;
//     const srcFormat = gl.RGBA;
//     const srcType = gl.UNSIGNED_BYTE;
//     const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue
//     gl.texImage2D(
//         gl.TEXTURE_2D,
//         level,
//         internalFormat,
//         width,
//         height,
//         border,
//         srcFormat,
//         srcType,
//         pixel,
//     );

//     const image = new Image();
//     image.onload = () => {
//         gl.bindTexture(gl.TEXTURE_2D, texture);
//         gl.texImage2D(
//             gl.TEXTURE_2D,
//             level,
//             internalFormat,
//             srcFormat,
//             srcType,
//             image,
//         );

//         // WebGL1 has different requirements for power of 2 images
//         // vs. non power of 2 images so check if the image is a
//         // power of 2 in both dimensions.
//         if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
//             // Yes, it's a power of 2. Generate mips.
//             gl.generateMipmap(gl.TEXTURE_2D);
//         } else {
//             // No, it's not a power of 2. Turn off mips and set
//             // wrapping to clamp to edge
//             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
//             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
//             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
//         }
//     };
//     image.src = url;

//     return texture;
// }

// function isPowerOf2(value) {
//     return (value & (value - 1)) === 0;
// }

// 将“webgl-demo.js”中的 loadTexture() 函数替换为 initTexture
function initTexture(gl) {
    const texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);

    // 因为视频必须通过互联网下载
    // 可能需要一些时间才能准备好
    // 因此在纹理中放置一个像素，以便我们
    // 可以立即使用它。
    const level = 0;
    const internalFormat = gl.RGBA;
    const width = 1;
    const height = 1;
    const border = 0;
    const srcFormat = gl.RGBA;
    const srcType = gl.UNSIGNED_BYTE;
    const pixel = new Uint8Array([0, 0, 255, 255]); // 不透明的蓝色
    gl.texImage2D(
        gl.TEXTURE_2D,
        level,
        internalFormat,
        width,
        height,
        border,
        srcFormat,
        srcType,
        pixel,
    );

    // 关闭 mips 并将包裹（wrapping）设置为边缘分割（clamp to edge）
    // 这样无论视频的尺寸如何，都可以正常工作。
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

    return texture;
}


// 更新
function updateTexture(gl, texture, video) {
    const level = 0;
    const internalFormat = gl.RGBA;
    const srcFormat = gl.RGBA;
    const srcType = gl.UNSIGNED_BYTE;
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(
        gl.TEXTURE_2D,
        level,
        internalFormat,
        srcFormat,
        srcType,
        video,
    );
}


// 获取视频
function setupVideo(url) {
    const video = document.createElement("video");

    let playing = false;
    let timeupdate = false;

    video.playsInline = true;
    video.muted = true;
    video.loop = true;

    // 等待以下两个事件
    // 确保 video 中已有数据

    video.addEventListener(
        "playing",
        () => {
            playing = true;
            checkReady();
        },
        true,
    );

    video.addEventListener(
        "timeupdate",
        () => {
            timeupdate = true;
            checkReady();
        },
        true,
    );

    video.src = url;
    video.play();

    function checkReady() {
        if (playing && timeupdate) {
            copyVideo = true;
        }
    }

    return video;
}

